package com.zhike.api.controller.group;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zhike.common.dto.GroupCreateDTO;
import com.zhike.common.dto.GroupDeleteMemberDTO;
import com.zhike.common.dto.GroupDissDTO;
import com.zhike.common.dto.GroupInviteJoinDTO;
import com.zhike.common.dto.GroupMemberEntity;
import com.zhike.common.dto.GroupMemberProhibitDTO;
import com.zhike.common.dto.GroupNoticeDTO;
import com.zhike.common.dto.GroupProhibitDTO;
import com.zhike.common.dto.GroupReqDTO;
import com.zhike.common.dto.GroupSetAdminDTO;
import com.zhike.common.dto.GroupTransDTO;
import com.zhike.common.dto.GroupUpdateNameDTO;
import com.zhike.common.dto.GroupUserDTO;
import com.zhike.common.dto.GroupIdDTO;
import com.zhike.common.dto.GroupUserNicknameDTO;
import com.zhike.common.dto.GroupVerficateDTO;
import com.zhike.common.dto.R;
import com.zhike.common.enums.ResultCode;
import com.zhike.common.enums.YesNoEnum;
import com.zhike.common.model.GroupBase;
import com.zhike.common.model.GroupReq;
import com.zhike.common.vo.GroupReqVO;
import com.zhike.common.vo.UserInfo4Cache;
import com.zhike.service.group.IGroupService;
import com.zhike.service.messages.IChatSessionService;
import com.zhike.service.system.ISystemService;
import com.zhike.utils.cache.UsersInfoCacheProvider;
import com.zhike.utils.file.FileAvatar;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@RestController
@RequestMapping("api/zkim/group")
@Api(tags = "群组模块")
public class GroupController {

    @Autowired
    private IGroupService groupService;

    @Autowired
    private ISystemService systemService;

    @Autowired
    private UsersInfoCacheProvider usersInfoCacheProvider;

    @Autowired
    private IChatSessionService chatSessionService;

    @Autowired
    private FileAvatar fileAvatar;

    @ApiOperation(value = "群头像", notes = "群头像下载地址")
    @GetMapping("avatar/{groupId}")
    public R<String> getUserAvatar(@PathVariable("groupId") String groupId) {
        return R.success(fileAvatar.getGroupAvatarUrl(groupId));
    }

    @ApiOperation(value = "查询群组列表接口")
    @PostMapping("queryGroupList")
    public R<List<GroupBase>> queryGroupList() {
        UserInfo4Cache uc = systemService.getUserInfo();
        List<GroupBase> list = groupService.queryGroupInfoList(uc.getFakeUid());
        return R.success(list);
    }

    @ApiOperation(value = "查询群基本信息接口")
    @PostMapping("queryGroupInfo")
    public R<GroupBase> queryGroupInfo(@RequestBody GroupIdDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        GroupBase ge = groupService.queryGroupInfo(dto.getGroupId(), uc.getFakeUid());
        if (ge == null) {
            return R.rsp(ResultCode.GROUP_NO_EXIST);
        }
        if (StringUtils.isNotBlank(ge.getNoticeUpdateuid())) {
            UserInfo4Cache updater = usersInfoCacheProvider.get(ge.getNoticeUpdateuid());
            ge.setNoticeUpdateNickname(updater.getNickName());
        }

        return R.success(ge);
    }

    @ApiOperation(value = "查询群成员列表接口")
    @PostMapping("queryGroupPersonList")
    public R<List<GroupMemberEntity>> queryGroupPersonList(@Validated @RequestBody GroupIdDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        return R.success(groupService.queryGroupPersonList(uc.getFakeUid(), dto));
    }

    @ApiOperation(value = "创建群组", notes = "参数members只需传入成员,如果没有则传空")
    @PostMapping("createGroup")
    public R<Boolean> createGroup(@Valid @RequestBody GroupCreateDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        // 群主
        GroupMemberEntity gme = new GroupMemberEntity();
        gme.setNickname(uc.getNickName());
        gme.setUserId(uc.getFakeUid());
        gme.setIsAdmin(YesNoEnum.NO.getValue());
        return R.success(groupService.createGroup(gme, dto.getMembers()));
    }

    @ApiOperation(value = "修改群名称接口")
    @PostMapping("updateGroupName")
    public R<Boolean> updateGroupName(@Validated @RequestBody GroupUpdateNameDTO dto) {
        return R.success(groupService.updateGroupName(dto));
    }

    @ApiOperation(value = "修改\"我\"的群昵称接口")
    @PostMapping("updateGroupUserNickName")
    public R<Boolean> updateGroupUserNickName(@Validated @RequestBody GroupUserNicknameDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        return R.success(groupService.updateGroupUserNickName(uc.getFakeUid(), dto));
    }

    @ApiOperation(value = "打开/关闭群验证")
    @PostMapping("setVerificate")
    public R<Boolean> setVerificate(@Validated @RequestBody GroupVerficateDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        return R.success(groupService.updateGroupVerficate(uc.getFakeUid(), dto));
    }

    @ApiOperation(value = "全员禁言/解除", notes = "全员禁言（action:1丶是 0丶否）")
    @PostMapping("setProhibitMsg")
    public R<Boolean> setProhibitMsg(@Validated @RequestBody GroupProhibitDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        return R.success(groupService.setAllProhibitMsg(uc.getFakeUid(), uc.getNickName(), dto));
    }

    @ApiOperation(value = "成员禁言/解除", notes = "禁言(action:1是0否)  interval:-1永久禁言")
    @PostMapping("prohibitMember")
    public R<Boolean> prohibitMember(@Validated @RequestBody GroupMemberProhibitDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        return R.success(groupService.prohibitMembers(uc.getFakeUid(), uc.getNickName(), dto));
    }

    @ApiOperation(value = "修改群公告")
    @PostMapping("updateGroupNotice")
    public R<Boolean> updateGroupNotice(@Validated @RequestBody GroupNoticeDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        return R.success(groupService.updateGroupNotice(uc.getFakeUid(), dto));
    }

    @ApiOperation(value = "删除群成员")
    @PostMapping("deleteGroupPerson")
    public R<Boolean> deleteGroupPerson(@Valid @RequestBody GroupDeleteMemberDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        return R.success(groupService.deleteGroupPerson(uc, dto));
    }

    @ApiOperation(value = "用户主动退群")
    @PostMapping("exitGroup")
    public R<Boolean> exitTheGroup(@Valid @RequestBody GroupIdDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        return R.success(groupService.exitGroup(uc, dto));
    }

    @ApiOperation(value = "邀请入群接口")
    @PostMapping("inviteToJoinTheGroup")
    public R<Boolean> inviteToJoinTheGroup(@Validated @RequestBody GroupInviteJoinDTO dto) throws Exception {
        UserInfo4Cache uc = systemService.getUserInfo();
        return R.success(groupService.inviteToJoinTheGroup(uc.getFakeUid(), uc.getNickName(), dto));
    }

    @ApiOperation(value = "邀请入群通知列表", notes = "管理员查看")
    @PostMapping("inviteToGroupReqList")
    public R<GroupReqVO> inviteToGroupReqList(@Validated @RequestBody GroupIdDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        List<GroupReq> list = groupService.inviteToGroupReqList(uc.getFakeUid(), dto.getGroupId());
        List<GroupReqVO> newList = new ArrayList<>();
        for (GroupReq req : list) {
            UserInfo4Cache user = usersInfoCacheProvider.get(req.getUserUid());
            UserInfo4Cache beUser = usersInfoCacheProvider.get(req.getBeUserUid());
            GroupReqVO vo = new GroupReqVO();
            vo.setId(req.getId());
            vo.setGroupId(req.getGId());
            vo.setUserUid(req.getUserUid());
            vo.setNickname(user.getNickName());
            vo.setBeUserUid(req.getBeUserUid());
            vo.setBeNickname(beUser.getNickName());
            vo.setBeDesc(req.getBeDesc());
            vo.setBeTimestamp(req.getBeTimestamp());
            vo.setStatus(req.getStatus());
            newList.add(vo);
        }

        // 清除消息通知数
        List<String> uids = groupService.getAdminUsersIds(dto.getGroupId());
        chatSessionService.updateNotifyCount(dto.getGroupId(), uids, 0);
        return R.success(newList);
    }

    @ApiOperation(value = "转让本群接口（群主可用）")
    @PostMapping("transferenceGroup")
    public R<Boolean> transferenceGroup(@RequestBody GroupTransDTO dto, HttpServletRequest req) {
        UserInfo4Cache uc = systemService.getUserInfo();
        return R.success(groupService.transferenceGroup(uc.getFakeUid(), uc.getNickName(), dto));
    }

    @ApiOperation(value = "解散群")
    @PostMapping("dissolutionGroup")
    public R<Boolean> dissolutionGroup(@Validated @RequestBody GroupDissDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        return R.success(groupService.dissolutionGroup(uc.getFakeUid(), uc.getNickName(), dto));
    }

    @ApiOperation(value = "设置/解除群管理员", notes = "isAdmin设置1是群管理,0是取消群管理;")
    @PostMapping("setAdmin")
    public R<Boolean> setAdministrator(@Valid @RequestBody GroupSetAdminDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        // 不能为自己设置
        for (GroupUserDTO d : dto.getTargetUsers()) {
            if (d.getUserId() != null && d.getUserId().equals(uc.getFakeUid())) {
                return R.rsp(ResultCode.GROUP_SET_NOSELF);
            }
        }
        return R.success(groupService.setAdministrator(uc.getFakeUid(), uc.getNickName(), dto));
    }

    @ApiOperation(value = "同意入群")
    @PostMapping("agree")
    public R<Boolean> agree(@Validated @RequestBody GroupReqDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        return R.success(groupService.agree(uc.getFakeUid(), uc.getNickName(), dto));
    }

    @ApiOperation(value = "拒绝入群")
    @PostMapping("refuse")
    public R<Boolean> refuse(@Validated @RequestBody GroupReqDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        return R.success(groupService.refuse(uc.getFakeUid(), uc.getNickName(), dto));
    }
}
